import {
  registerDecorator,
  ValidationOptions,
  ValidatorConstraint,
  ValidatorConstraintInterface,
  ValidationArguments
} from 'class-validator'
import { Injectable } from '@nestjs/common'

/**
 * 密码强度验证器
 */
@ValidatorConstraint({ name: 'isStrongPassword', async: false })
@Injectable()
export class IsStrongPasswordConstraint implements ValidatorConstraintInterface {
  validate(password: string, args: ValidationArguments) {
    if (!password) return false

    // 至少8位，包含大小写字母、数字和特殊字符
    const strongPasswordRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/
    return strongPasswordRegex.test(password)
  }

  defaultMessage(args: ValidationArguments) {
    return '密码必须至少8位，包含大小写字母、数字和特殊字符'
  }
}

/**
 * 强密码验证装饰器
 */
export function IsStrongPassword(validationOptions?: ValidationOptions) {
  return function (object: object, propertyName: string) {
    registerDecorator({
      target: object.constructor,
      propertyName: propertyName,
      options: validationOptions,
      constraints: [],
      validator: IsStrongPasswordConstraint
    })
  }
}

/**
 * 手机号验证器
 */
@ValidatorConstraint({ name: 'isPhoneNumber', async: false })
@Injectable()
export class IsPhoneNumberConstraint implements ValidatorConstraintInterface {
  validate(phone: string, args: ValidationArguments) {
    if (!phone) return false

    // 中国大陆手机号验证
    const phoneRegex = /^1[3-9]\d{9}$/
    return phoneRegex.test(phone)
  }

  defaultMessage(args: ValidationArguments) {
    return '请输入有效的手机号码'
  }
}

/**
 * 手机号验证装饰器
 */
export function IsPhoneNumber(validationOptions?: ValidationOptions) {
  return function (object: object, propertyName: string) {
    registerDecorator({
      target: object.constructor,
      propertyName: propertyName,
      options: validationOptions,
      constraints: [],
      validator: IsPhoneNumberConstraint
    })
  }
}

/**
 * 用户名验证器
 */
@ValidatorConstraint({ name: 'isUsername', async: false })
@Injectable()
export class IsUsernameConstraint implements ValidatorConstraintInterface {
  validate(username: string, args: ValidationArguments) {
    if (!username) return false

    // 用户名：3-20位，字母、数字、下划线，不能以数字开头
    const usernameRegex = /^[a-zA-Z][a-zA-Z0-9_]{2,19}$/
    return usernameRegex.test(username)
  }

  defaultMessage(args: ValidationArguments) {
    return '用户名必须3-20位，以字母开头，只能包含字母、数字和下划线'
  }
}

/**
 * 用户名验证装饰器
 */
export function IsUsername(validationOptions?: ValidationOptions) {
  return function (object: object, propertyName: string) {
    registerDecorator({
      target: object.constructor,
      propertyName: propertyName,
      options: validationOptions,
      constraints: [],
      validator: IsUsernameConstraint
    })
  }
}

/**
 * 文件类型验证器
 */
@ValidatorConstraint({ name: 'isFileType', async: false })
@Injectable()
export class IsFileTypeConstraint implements ValidatorConstraintInterface {
  validate(filename: string, args: ValidationArguments) {
    if (!filename) return false

    const allowedTypes = args.constraints[0] || []
    const fileExtension = filename.split('.').pop()?.toLowerCase()

    return allowedTypes.includes(fileExtension)
  }

  defaultMessage(args: ValidationArguments) {
    const allowedTypes = args.constraints[0] || []
    return `文件类型必须是以下之一：${allowedTypes.join(', ')}`
  }
}

/**
 * 文件类型验证装饰器
 */
export function IsFileType(allowedTypes: string[], validationOptions?: ValidationOptions) {
  return function (object: object, propertyName: string) {
    registerDecorator({
      target: object.constructor,
      propertyName: propertyName,
      options: validationOptions,
      constraints: [allowedTypes],
      validator: IsFileTypeConstraint
    })
  }
}

/**
 * 日期范围验证器
 */
@ValidatorConstraint({ name: 'isDateRange', async: false })
@Injectable()
export class IsDateRangeConstraint implements ValidatorConstraintInterface {
  validate(value: any, args: ValidationArguments) {
    if (!value) return false

    const [startDateProperty, endDateProperty] = args.constraints
    const startDate = (args.object as any)[startDateProperty]
    const endDate = (args.object as any)[endDateProperty]

    if (!startDate || !endDate) return true // 如果其中一个为空，跳过验证

    return new Date(startDate) <= new Date(endDate)
  }

  defaultMessage(args: ValidationArguments) {
    return '开始日期不能晚于结束日期'
  }
}

/**
 * 日期范围验证装饰器
 */
export function IsDateRange(startDateProperty: string, endDateProperty: string, validationOptions?: ValidationOptions) {
  return function (object: object, propertyName: string) {
    registerDecorator({
      target: object.constructor,
      propertyName: propertyName,
      options: validationOptions,
      constraints: [startDateProperty, endDateProperty],
      validator: IsDateRangeConstraint
    })
  }
}

/**
 * 密码确认验证器
 */
@ValidatorConstraint({ name: 'isPasswordMatch', async: false })
@Injectable()
export class IsPasswordMatchConstraint implements ValidatorConstraintInterface {
  validate(confirmPassword: string, args: ValidationArguments) {
    const password = (args.object as any).password
    return password === confirmPassword
  }

  defaultMessage(args: ValidationArguments) {
    return '确认密码与密码不匹配'
  }
}

/**
 * 密码确认验证装饰器
 */
export function IsPasswordMatch(validationOptions?: ValidationOptions) {
  return function (object: object, propertyName: string) {
    registerDecorator({
      target: object.constructor,
      propertyName: propertyName,
      options: validationOptions,
      constraints: [],
      validator: IsPasswordMatchConstraint
    })
  }
}

/**
 * URL验证器（支持中文域名）
 */
@ValidatorConstraint({ name: 'isUrlWithChinese', async: false })
@Injectable()
export class IsUrlWithChineseConstraint implements ValidatorConstraintInterface {
  validate(url: string, args: ValidationArguments) {
    if (!url) return false

    try {
      new URL(url)
      return true
    } catch {
      return false
    }
  }

  defaultMessage(args: ValidationArguments) {
    return '请输入有效的URL地址'
  }
}

/**
 * URL验证装饰器（支持中文域名）
 */
export function IsUrlWithChinese(validationOptions?: ValidationOptions) {
  return function (object: object, propertyName: string) {
    registerDecorator({
      target: object.constructor,
      propertyName: propertyName,
      options: validationOptions,
      constraints: [],
      validator: IsUrlWithChineseConstraint
    })
  }
}

/**
 * 颜色值验证器（支持HEX、RGB、RGBA）
 */
@ValidatorConstraint({ name: 'isColor', async: false })
@Injectable()
export class IsColorConstraint implements ValidatorConstraintInterface {
  validate(color: string, args: ValidationArguments) {
    if (!color) return false

    // HEX颜色
    const hexRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/
    // RGB颜色
    const rgbRegex =
      /^rgb\(\s*([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\s*,\s*([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\s*,\s*([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\s*\)$/
    // RGBA颜色
    const rgbaRegex =
      /^rgba\(\s*([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\s*,\s*([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\s*,\s*([01]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\s*,\s*((0\.[0-9]+)|[01])\s*\)$/

    return hexRegex.test(color) || rgbRegex.test(color) || rgbaRegex.test(color)
  }

  defaultMessage(args: ValidationArguments) {
    return '请输入有效的颜色值（HEX、RGB或RGBA格式）'
  }
}

/**
 * 颜色值验证装饰器
 */
export function IsColor(validationOptions?: ValidationOptions) {
  return function (object: object, propertyName: string) {
    registerDecorator({
      target: object.constructor,
      propertyName: propertyName,
      options: validationOptions,
      constraints: [],
      validator: IsColorConstraint
    })
  }
}
